package com.yfqy.app.modules.wechat.service;

import com.yfqy.app.modules.wechat.config.WechatPayConfig;
import com.yfqy.app.modules.wechat.model.WechatPayOrderRequest;
import com.yfqy.app.modules.wechat.model.WechatPayOrderResponse;
import com.yfqy.app.modules.wechat.model.WechatRefundRequest;
import com.yfqy.app.modules.wechat.model.WechatRefundResponse;
import com.yfqy.app.modules.wechat.util.WechatPayJsApiUtil;
import com.yfqy.app.modules.wechat.util.WechatPayUtil;
import com.yfqy.app.modules.wechat.util.XMLUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WechatPayService {

    @Autowired
    private WechatPayConfig wechatPayConfig;
    @Autowired
    @Qualifier("wechatCertHttpClient")
    private CloseableHttpClient wechatCertHttpClient;

    /**
     * 创建支付订单
     */
    public WechatPayOrderResponse createOrder(WechatPayOrderRequest request) {
        try {
            // 构建请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", wechatPayConfig.getAppId());
            params.put("mch_id", wechatPayConfig.getMchId());
            params.put("nonce_str", WechatPayUtil.generateNonceStr());
            params.put("body", request.getBody());
            params.put("out_trade_no", request.getOutTradeNo());
            params.put("total_fee", String.valueOf(request.getTotalFee()));
            params.put("spbill_create_ip", request.getSpbillCreateIp() != null ?
                    request.getSpbillCreateIp() : WechatPayUtil.getClientIp());
            params.put("notify_url", wechatPayConfig.getNotifyUrl());
            params.put("trade_type", "JSAPI");
            params.put("openid", request.getOpenid());

            // 添加可选参数
            if (request.getAttach() != null) {
                params.put("attach", request.getAttach());
            }
            if (request.getDeviceInfo() != null) {
                params.put("device_info", request.getDeviceInfo());
            }
            if (request.getDetail() != null) {
                params.put("detail", request.getDetail());
            }
            if (request.getFeeType() != null) {
                params.put("fee_type", request.getFeeType());
            }
            if (request.getTimeStart() != null) {
                params.put("time_start", request.getTimeStart());
            }
            if (request.getTimeExpire() != null) {
                params.put("time_expire", request.getTimeExpire());
            }
            if (request.getGoodsTag() != null) {
                params.put("goods_tag", request.getGoodsTag());
            }
            if (request.getProductId() != null) {
                params.put("product_id", request.getProductId());
            }
            if (request.getLimitPay() != null) {
                params.put("limit_pay", request.getLimitPay());
            }
            if (request.getSceneInfo() != null) {
                params.put("scene_info", request.getSceneInfo());
            }

            // 生成签名
            String sign = WechatPayUtil.generateSign(params, wechatPayConfig.getApiKey());
            params.put("sign", sign);

            // 转换为XML
            String xmlRequest = XMLUtil.convertMapToXml(params);
            log.info("统一下单请求参数: {}", xmlRequest);

            // 发送请求
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(wechatPayConfig.getUnifiedOrderUrl());
            httpPost.setHeader("Content-Type", "application/xml; charset=UTF-8");
            httpPost.setEntity(new StringEntity(xmlRequest, StandardCharsets.UTF_8));

            CloseableHttpResponse response = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("统一下单响应: {}", responseBody);

            // 解析响应
            Map<String, String> responseMap = XMLUtil.parseXmlToMap(responseBody);

            WechatPayOrderResponse orderResponse = new WechatPayOrderResponse();
            orderResponse.setReturnCode(responseMap.get("return_code"));
            orderResponse.setReturnMsg(responseMap.get("return_msg"));

            if ("SUCCESS".equals(responseMap.get("return_code"))) {
                orderResponse.setAppid(responseMap.get("appid"));
                orderResponse.setMchId(responseMap.get("mch_id"));
                orderResponse.setDeviceInfo(responseMap.get("device_info"));
                orderResponse.setNonceStr(responseMap.get("nonce_str"));
                orderResponse.setSign(responseMap.get("sign"));
                orderResponse.setResultCode(responseMap.get("result_code"));
                orderResponse.setErrCode(responseMap.get("err_code"));
                orderResponse.setErrCodeDes(responseMap.get("err_code_des"));

                if ("SUCCESS".equals(responseMap.get("result_code"))) {
                    orderResponse.setTradeType(responseMap.get("trade_type"));
                    orderResponse.setPrepayId(responseMap.get("prepay_id"));
                    orderResponse.setCodeUrl(responseMap.get("code_url"));
                }
            }

            httpClient.close();
            return orderResponse;

        } catch (Exception e) {
            log.error("创建支付订单异常", e);
            return null;
        }
    }

    /**
     * 生成小程序支付参数
     */
    public Map<String, String> generateJsApiParams(String prepayId) {
        return WechatPayJsApiUtil.generateJsApiParams(
                wechatPayConfig.getAppId(),
                prepayId,
                wechatPayConfig.getApiKey()
        );
    }

    /**
     * 查询订单状态
     */
    public WechatPayOrderResponse queryOrder(String outTradeNo) {
        try {
            // 构建请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", wechatPayConfig.getAppId());
            params.put("mch_id", wechatPayConfig.getMchId());
            params.put("out_trade_no", outTradeNo);
            params.put("nonce_str", WechatPayUtil.generateNonceStr());

            // 生成签名
            String sign = WechatPayUtil.generateSign(params, wechatPayConfig.getApiKey());
            params.put("sign", sign);

            // 转换为XML
            String xmlRequest = XMLUtil.convertMapToXml(params);
            log.info("查询订单请求参数: {}", xmlRequest);

            // 发送请求
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(wechatPayConfig.getOrderQueryUrl());
            httpPost.setHeader("Content-Type", "application/xml; charset=UTF-8");
            httpPost.setEntity(new StringEntity(xmlRequest, StandardCharsets.UTF_8));

            CloseableHttpResponse response = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("查询订单响应: {}", responseBody);

            // 解析响应
            Map<String, String> responseMap = XMLUtil.parseXmlToMap(responseBody);

            WechatPayOrderResponse orderResponse = new WechatPayOrderResponse();
            orderResponse.setReturnCode(responseMap.get("return_code"));
            orderResponse.setReturnMsg(responseMap.get("return_msg"));

            if ("SUCCESS".equals(responseMap.get("return_code"))) {
                orderResponse.setAppid(responseMap.get("appid"));
                orderResponse.setMchId(responseMap.get("mch_id"));
                orderResponse.setNonceStr(responseMap.get("nonce_str"));
                orderResponse.setSign(responseMap.get("sign"));
                orderResponse.setResultCode(responseMap.get("result_code"));
                orderResponse.setErrCode(responseMap.get("err_code"));
                orderResponse.setErrCodeDes(responseMap.get("err_code_des"));
                orderResponse.setTradeState(responseMap.get("trade_state"));
            }

            httpClient.close();
            return orderResponse;

        } catch (Exception e) {
            log.error("查询订单异常", e);
            return null;
        }
    }

    /**
     * 申请退款
     */
    public WechatRefundResponse refund(WechatRefundRequest request) {
        try {
            // 构建请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", wechatPayConfig.getAppId());
            params.put("mch_id", wechatPayConfig.getMchId());
            params.put("nonce_str", WechatPayUtil.generateNonceStr());

            // transaction_id、out_trade_no二选一
            if (request.getTransactionId() != null && !request.getTransactionId().isEmpty()) {
                params.put("transaction_id", request.getTransactionId());
            } else if (request.getOutTradeNo() != null && !request.getOutTradeNo().isEmpty()) {
                params.put("out_trade_no", request.getOutTradeNo());
            } else {
                throw new RuntimeException("transaction_id和out_trade_no必须提供其中一个");
            }

            params.put("out_refund_no", request.getOutRefundNo());
            params.put("total_fee", String.valueOf(request.getTotalFee()));
            params.put("refund_fee", String.valueOf(request.getRefundFee()));

            // 添加可选参数
            if (request.getRefundFeeType() != null) {
                params.put("refund_fee_type", request.getRefundFeeType());
            }
            if (request.getRefundDesc() != null) {
                params.put("refund_desc", request.getRefundDesc());
            }
            if (request.getRefundAccount() != null) {
                params.put("refund_account", request.getRefundAccount());
            }
            if (request.getNotifyUrl() != null) {
                params.put("notify_url", request.getNotifyUrl());
            } else {
                params.put("notify_url", wechatPayConfig.getRefundNotifyUrl());
            }

            // 生成签名
            String sign = WechatPayUtil.generateSign(params, wechatPayConfig.getApiKey());
            params.put("sign", sign);

            // 转换为XML
            String xmlRequest = XMLUtil.convertMapToXml(params);
            log.info("申请退款请求参数: {}", xmlRequest);

            HttpPost httpPost = new HttpPost(wechatPayConfig.getRefundUrl());
            httpPost.setHeader("Content-Type", "application/xml; charset=UTF-8");
            httpPost.setEntity(new StringEntity(xmlRequest, StandardCharsets.UTF_8));

            // 支持SSL证书的HttpClient
            CloseableHttpResponse response = wechatCertHttpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("申请退款响应: {}", responseBody);

            // 解析响应
            Map<String, String> responseMap = XMLUtil.parseXmlToMap(responseBody);

            WechatRefundResponse refundResponse = new WechatRefundResponse();
            refundResponse.setReturnCode(responseMap.get("return_code"));
            refundResponse.setReturnMsg(responseMap.get("return_msg"));

            if ("SUCCESS".equals(responseMap.get("return_code"))) {
                refundResponse.setAppid(responseMap.get("appid"));
                refundResponse.setMchId(responseMap.get("mch_id"));
                refundResponse.setNonceStr(responseMap.get("nonce_str"));
                refundResponse.setSign(responseMap.get("sign"));
                refundResponse.setResultCode(responseMap.get("result_code"));
                refundResponse.setErrCode(responseMap.get("err_code"));
                refundResponse.setErrCodeDes(responseMap.get("err_code_des"));

                if ("SUCCESS".equals(responseMap.get("result_code"))) {
                    refundResponse.setTransactionId(responseMap.get("transaction_id"));
                    refundResponse.setOutTradeNo(responseMap.get("out_trade_no"));
                    refundResponse.setOutRefundNo(responseMap.get("out_refund_no"));
                    refundResponse.setRefundId(responseMap.get("refund_id"));

                    // 解析金额字段
                    if (responseMap.get("refund_fee") != null) {
                        refundResponse.setRefundFee(Integer.valueOf(responseMap.get("refund_fee")));
                    }
                    if (responseMap.get("settlement_refund_fee") != null) {
                        refundResponse.setSettlementRefundFee(Integer.valueOf(responseMap.get("settlement_refund_fee")));
                    }
                    if (responseMap.get("total_fee") != null) {
                        refundResponse.setTotalFee(Integer.valueOf(responseMap.get("total_fee")));
                    }
                    if (responseMap.get("settlement_total_fee") != null) {
                        refundResponse.setSettlementTotalFee(Integer.valueOf(responseMap.get("settlement_total_fee")));
                    }
                    if (responseMap.get("cash_fee") != null) {
                        refundResponse.setCashFee(Integer.valueOf(responseMap.get("cash_fee")));
                    }
                    if (responseMap.get("cash_refund_fee") != null) {
                        refundResponse.setCashRefundFee(Integer.valueOf(responseMap.get("cash_refund_fee")));
                    }
                    if (responseMap.get("coupon_refund_fee") != null) {
                        refundResponse.setCouponRefundFee(Integer.valueOf(responseMap.get("coupon_refund_fee")));
                    }
                    if (responseMap.get("coupon_refund_count") != null) {
                        refundResponse.setCouponRefundCount(Integer.valueOf(responseMap.get("coupon_refund_count")));
                    }

                    refundResponse.setFeeType(responseMap.get("fee_type"));
                    refundResponse.setCashFeeType(responseMap.get("cash_fee_type"));
                }
            }

            return refundResponse;

        } catch (Exception e) {
            log.error("申请退款异常", e);
            return null;
        }
    }

    /**
     * 查询退款
     */
    public WechatRefundResponse queryRefund(String outRefundNo) {
        try {
            // 构建请求参数
            Map<String, String> params = new HashMap<>();
            params.put("appid", wechatPayConfig.getAppId());
            params.put("mch_id", wechatPayConfig.getMchId());
            params.put("out_refund_no", outRefundNo);
            params.put("nonce_str", WechatPayUtil.generateNonceStr());

            // 生成签名
            String sign = WechatPayUtil.generateSign(params, wechatPayConfig.getApiKey());
            params.put("sign", sign);

            // 转换为XML
            String xmlRequest = XMLUtil.convertMapToXml(params);
            log.info("查询退款请求参数: {}", xmlRequest);

            // 发送请求
            CloseableHttpClient httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(wechatPayConfig.getRefundQueryUrl());
            httpPost.setHeader("Content-Type", "application/xml; charset=UTF-8");
            httpPost.setEntity(new StringEntity(xmlRequest, StandardCharsets.UTF_8));

            CloseableHttpResponse response = httpClient.execute(httpPost);
            String responseBody = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
            log.info("查询退款响应: {}", responseBody);

            // 解析响应
            Map<String, String> responseMap = XMLUtil.parseXmlToMap(responseBody);

            WechatRefundResponse refundResponse = new WechatRefundResponse();
            refundResponse.setReturnCode(responseMap.get("return_code"));
            refundResponse.setReturnMsg(responseMap.get("return_msg"));

            if ("SUCCESS".equals(responseMap.get("return_code"))) {
                refundResponse.setResultCode(responseMap.get("result_code"));
                refundResponse.setErrCode(responseMap.get("err_code"));
                refundResponse.setErrCodeDes(responseMap.get("err_code_des"));

                if ("SUCCESS".equals(responseMap.get("result_code"))) {
                    refundResponse.setTransactionId(responseMap.get("transaction_id"));
                    refundResponse.setOutTradeNo(responseMap.get("out_trade_no"));
                    refundResponse.setOutRefundNo(responseMap.get("out_refund_no_0"));
                    refundResponse.setRefundId(responseMap.get("refund_id_0"));
                }
            }

            httpClient.close();
            return refundResponse;

        } catch (Exception e) {
            log.error("查询退款异常", e);
            return null;
        }
    }

    /**
     * 创建支持SSL证书的HttpClient
     * 注意：实际使用时需要配置正确的证书路径和密码
     */
//    private CloseableHttpClient createSSLHttpClient() throws Exception {
//        // 这里需要配置微信支付的SSL证书
//        // 证书文件通常命名为 apiclient_cert.p12
//        // 证书密码通常是商户号
//
//        try {
//            // 加载证书
//            KeyStore keyStore = KeyStore.getInstance("PKCS12");
//            String certPath = wechatPayConfig.getWechatpayCertPath(); // 证书路径
//            String certPassword = wechatPayConfig.getMchId(); // 证书密码（通常是商户号）
//
//            // 注意：这里简化处理，实际项目中需要正确配置证书路径
//            try (InputStream instream = WechatPayService.class.getClassLoader().getResourceAsStream(certPath)) {
//                keyStore.load(instream, certPassword.toCharArray());
//            }
//
//
//            SSLContext sslcontext = SSLContexts.custom()
//                    .loadKeyMaterial(keyStore, certPassword.toCharArray())
//                    .build();
//
//            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
//                    sslcontext,
//                    new String[]{"TLSv1"},
//                    null,
//                    SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
//
//            return HttpClients.custom()
//                    .setSSLSocketFactory(sslsf)
//                    .build();
//
//            // 临时返回默认客户端，实际项目中需要配置SSL证书
//            //log.warn("警告：当前使用默认HttpClient，生产环境需要配置SSL证书");
//            //return HttpClients.createDefault();
//
//        } catch (Exception e) {
//            log.error("创建SSL HttpClient失败，使用默认HttpClient", e);
//            return HttpClients.createDefault();
//        }
//    }

    /**
     * 创建带PKCS12证书的HttpClient
     *
     * @return CloseableHttpClient
     */
    public CloseableHttpClient createPkcs12HttpClient() {
        try {
            // 加载PKCS12证书
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            String certPath = wechatPayConfig.getWechatpayCertPath(); // 证书路径
            String certPassword = wechatPayConfig.getMchId(); // 证书密码（通常是商户号）
            try (InputStream certStream = WechatPayService.class.getClassLoader().getResourceAsStream(certPath)) {
                keyStore.load(certStream, certPassword.toCharArray());
            }


            // 创建SSL上下文
            SSLContext sslContext = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, certPassword.toCharArray())
                    .build();

            // 创建SSL连接工厂
            SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(
                    sslContext,
                    new String[]{"TLSv1", "TLSv1.2", "TLSv1.3"}, // 支持的协议
                    null, // 支持的密码套件，null表示使用默认
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier()
            );

            // 创建HttpClient
            return HttpClients.custom()
                    .setSSLSocketFactory(sslSocketFactory)
                    .build();

        } catch (Exception e) {
            throw new RuntimeException("创建带证书的HttpClient失败", e);
        }
    }

}
